#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    FirstStepInit();//第一步初始化
    StyleInit();//样式初始化
    connect(ui->setting,SIGNAL(triggered()),this,SLOT(open_setting()));//设置
    connect(ui->use,SIGNAL(triggered()),this,SLOT(open_use()));//使用说明

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::StyleInit()
{
    QFile qssFile(":/test.qss");//加载qss
    qssFile.open(QFile::ReadOnly);
    if(qssFile.isOpen())
    {
        QString qss = QLatin1String(qssFile.readAll()); //读取
        qApp->setStyleSheet(qss);  //设置
        qssFile.close();
    }
    QList<QComboBox *> Comboboxs = ui->setting_continer->findChildren<QComboBox *>();//combobox的item大小改变必须通过代码实现
    foreach (QComboBox * c, Comboboxs)
    {
        c->setView(new QListView());
    }
    //菜单项的图标设置
    ui->setting->setIcon(QIcon(":/setting.svg"));
    ui->use->setIcon(QIcon(":/说明.svg"));


}
//页表初始化
void MainWindow::PageTableInit()
{
    srand((int)time(0));//设置随机种子
    page_layout=new QGridLayout(ui->my_view);
    int *a=new int[page_num];//用来装随机数的数组，要求不重复
    int i=0,j;
    for(i=0;i<page_num;i++)                    //产生page_num个随机数
    {
        a[i]=rand()%page_num;                //得到随机数(范围在0-page_num-1之间)
        for(j=0;j<i;j++)
        {
            if(a[i]==a[j]) {i--;break;}  //如果重复,重新产生随机数
        }//判断和前面的数是否重复

    }
    int row=page_num;//页表的行数=物理块数
    int column=2;//2列
    QLabel *l1,*l2;//表头
    l1=new QLabel("虚页号");
    l2=new QLabel("物理块号");
    l1->setAlignment(Qt::AlignCenter);
    l2->setAlignment(Qt::AlignCenter);
    l1->setStyleSheet("background-color:rgb(223, 249, 251);");
    l2->setStyleSheet("background-color:rgb(223, 249, 251);");
    page_layout->addWidget(l1,0,0);
    page_layout->addWidget(l2,0,1);
    QLabel *l3=new QLabel("count");
    l3->setAlignment(Qt::AlignCenter);
    l3->setStyleSheet("background-color:rgb(223, 249, 251);");
    page_layout->addWidget(l3,0,2);
    page=new Page(ui->my_view);
    for(int i=0;i<page_num;i++)
    {
        PageItem *page_item=new PageItem(i,a[i],0);
        MyLabel *page_index=new MyLabel();
        page_index->setText(QString("%1").arg(i,(int)log2((mem_size+out_mem_size)/page_size), 2, QLatin1Char('0')));//虚页号二进制地址长度=log(page_num)
        page_item->setText(QString("%1").arg(a[i],(int)log2(page_num), 2, QLatin1Char('0')));//实页号二进制地址长度=log(mem_size/page_size)=log(page_num)
        page_index->setStyleSheet("background-color:rgb(255, 85, 0);");
        page_item->setStyleSheet("background-color:rgb(255, 175, 0);");
        page_item->setAlignment(Qt::AlignCenter);
        page_index->setAlignment(Qt::AlignCenter);
        page->container.append(page_item);

        page_layout->addWidget(page_index,i+1,0);
        page_layout->addWidget(page_item,i+1,1);
        MyLabel *c=new MyLabel();
        c->setText(QString::number(page_item->count,10) );
        c->setAlignment(Qt::AlignCenter);
        c->setStyleSheet("background-color:#ff6b6b");
        page_layout->addWidget(c,i+1,2);
    }
    QLabel *label=new QLabel("页表");
    label->setAlignment(Qt::AlignCenter);
    label->setStyleSheet("background-color:rgb(223, 249, 251);");
    column++;
    page_layout->addWidget(label,row+1,0,1,column);
    page_layout->setMargin(0);
    page_layout->setSpacing(1);
    page->setLayout(page_layout);
    page->setStyleSheet("border:1px solid");
    int w=column*width+(column-1);
    int h=(row+1+1)*height+row;
    page->setGeometry(10,100,w,h);//x,y,w,h
    page->setFixedSize(w,h);//固定大小，不可缩放
    page->show();

}
//cache初始化
void MainWindow::CacheInit()
{
    cache_layout=new QGridLayout(ui->my_view);//创建布局，用来装cache这个控件
    //tag data1,data2
    int row=(cache_size/cache_block_size);//行数,这里一行就是一个cache块，没有将path_num可视化出来
    int column=1+cache_block_size;//列数
    for(int i=0;i<column;i++)//cache的表头：tag,data0,data1……
    {
        QLabel *l=new QLabel();
        l->setAlignment(Qt::AlignCenter);
        l->setStyleSheet("background-color:rgb(223, 249, 251);");
        if(i==0)
        {
            l->setText("tag");
        }
        else
        {
            l->setText(QString("data%1").arg(i-1,1, 10, QLatin1Char('0')));
        }
        cache_layout->addWidget(l,0,i);
    }
    cache=new Cache(ui->my_view);
    for(int i=0;i<row;i++)//生成cache中的每一个单元块
    {
        CacheItem *cache_item=new CacheItem(-1,0);//tag=-1,status=0

        for(int j=0;j<column;j++)
        {
            MyLabel *label=new MyLabel();
            if(j%(1+cache_block_size)==0)//tag的颜色
            {
                label->setStyleSheet("background-color:rgb(129,205,220);");
                label->setAlignment(Qt::AlignCenter);
            }
            else//data的颜色
            {
                label->setStyleSheet("background-color:rgb(221, 234, 246);");
                cache_item->data.append(label);
            }

            cache_layout->addWidget(label,i+1,j);//因为有表头占了一行，所以从i+1行开始添加
        }
        cache->container.append(cache_item);//在cache的逻辑容器中装生成的整个cache,包括tag和data
    }
    QLabel *label=new QLabel("Cache");//在最后加上cache这个容器的名字
    label->setAlignment(Qt::AlignCenter);
    label->setStyleSheet("background-color:rgb(223, 249, 251);");
    cache_layout->addWidget(label,row+1,0,1,column);//位置在第row+1行，第0列，占了1行column列ge2格子
    cache_layout->setMargin(0);//设置margin0
    cache_layout->setSpacing(1);//设置布局内间距1
    cache->setLayout(cache_layout);//给容器设置布局
    cache->setStyleSheet("border:1px solid");
    int w=column*width+(column-1);//cache容器的宽度，这个式子怎么来的可以先不管
    int h=(row+1+1)*height+row;//cache容器的高度
    cache->setGeometry(200,100,w,h);//x,y,w,h，前面的200，100的位置可以不用管，
    cache->setFixedSize(w,h);//设置容器固定大小
    cache->show();
}
//内存初始化
void MainWindow::MemInit()
{
    QGridLayout *grid=new QGridLayout(ui->my_view);
    mem=new Mem(ui->my_view);
    int row=mem_size/cache_block_size;//内存的一行有nByte数据，cache一块大小=nByte
    int column=cache_block_size;
    //按照cache的一块大小为内存的一行
    for(int i=0;i<row;i++)
    {
        for(int j=0;j<column;j++)
        {
            MyLabel *label=new MyLabel(QString("%1").arg(i*column+j,(int)log2(mem_size+out_mem_size), 2, QLatin1Char('0')));
            label->setStyleSheet("background-color:rgb(255, 170, 127);");
            label->setAlignment(Qt::AlignCenter);
            mem->container.append(label);
            grid->addWidget(label,i,j);
        }
    }
    QLabel *label=new QLabel("主存");
    label->setAlignment(Qt::AlignCenter);
    label->setStyleSheet("background-color:rgb(223, 249, 251);");
    grid->addWidget(label,row,0,1,column);
    grid->setMargin(0);
    grid->setSpacing(1);
    mem->setLayout(grid);
    mem->setStyleSheet("border:1px solid");
    int w=column*width+(column-1);
    int h=(row+1)*height+(row-1);
    mem->setGeometry(500,100,w,h);//x,y,w,h
    mem->setFixedSize(w,h);
    mem->show();
}

void MainWindow::OutMemInit()
{
    QGridLayout *grid=new QGridLayout(ui->my_view);
    out_mem=new Mem(ui->my_view);
    int row=out_mem_size/cache_block_size;//内存的一行有nByte数据，cache一块大小=nByte
    int column=cache_block_size;
    //按照cache的一块大小为内存的一行
    for(int i=0;i<row;i++)
    {
        for(int j=0;j<column;j++)
        {
            MyLabel *label=new MyLabel(QString("%1").arg(mem_size+i*column+j,(int)log2(mem_size+out_mem_size), 2, QLatin1Char('0')));
            label->setStyleSheet("background-color:rgb(255, 100, 100);");
            label->setAlignment(Qt::AlignCenter);
            out_mem->container.append(label);
            grid->addWidget(label,i,j);
        }
    }
    QLabel *label=new QLabel("外存");
    label->setAlignment(Qt::AlignCenter);
    label->setStyleSheet("background-color:rgb(223, 249, 251);");
    grid->addWidget(label,row,0,1,column);
    grid->setMargin(0);
    grid->setSpacing(1);
    out_mem->setLayout(grid);
    out_mem->setStyleSheet("border:1px solid");
    int w=column*width+(column-1);
    int h=(row+1)*height+(row-1);
    out_mem->setGeometry(700,100,w,h);//x,y,w,h
    out_mem->setFixedSize(w,h);
    out_mem->show();
}

int MainWindow::locate(int n)//给虚页号，得物理块号
{
    //遍历页表，找到其虚页号对应的实页号
    for (int i=0;i<page_num;i++)
    {

        QLayoutItem *t=page_layout->itemAtPosition(i+1,2);
        QLabel * page_count=qobject_cast<QLabel *>(t->widget());
        page_count->setText(QString::number( ++(page->container)[i]->count));//只要是访问了页表，那么所有页表项的count都+1
    }
    for (int i=0;i<page_num;i++)
    {
        if ((page->container)[i]->pageNum==n)
        {
            (page->container)[i]->count=0;//如果找到了，就把其count清空
            QLayoutItem *t=page_layout->itemAtPosition(i+1,2);
            QLabel * page_count=qobject_cast<QLabel *>(t->widget());
            page_count->setText(QString::number( (page->container)[i]->count));
            return (page->container)[i]->memNum;
        }
    }
    return -1;
}


void MainWindow::FirstStepInit()
{
    QSizePolicy sp_retain = ui->SecondStep->sizePolicy();
    sp_retain.setRetainSizeWhenHidden(true);
    ui->SecondStep->setSizePolicy(sp_retain);
    //隐藏第二步
    ui->SecondStep->hide();
}

void MainWindow::SecondStepInit()
{
    PageTableInit();
    CacheInit();
    MemInit();
    OutMemInit();
    QHBoxLayout *hlayout=new QHBoxLayout();
    hlayout->addWidget(page);
    hlayout->addWidget(cache);
    hlayout->addWidget(mem);
    hlayout->addWidget(out_mem);
    hlayout->setSpacing(100);
    ui->my_view->setLayout(hlayout);
}

void MainWindow::on_page_size_comboBox_currentTextChanged(const QString &arg1)
{
    this->page_size=arg1.toInt();
    page_num=mem_size/page_size;
}

void MainWindow::on_mem_size_comboBox_currentTextChanged(const QString &arg1)
{
    this->mem_size=arg1.toInt();
    out_mem_size=mem_size;
    page_num=mem_size/page_size;
}
void MainWindow::on_cache_block__size_comboBox_currentTextChanged(const QString &arg1)
{
    this->cache_block_size=arg1.toInt();
}

void MainWindow::on_cache_sizze_comboBox_currentTextChanged(const QString &arg1)
{
    this->cache_size=arg1.toInt();
}
void MainWindow::on_path_num_comboBox_currentTextChanged(const QString &arg1)
{
    this->path_num=arg1.toInt();
}

void MainWindow::on_algorithmcomboBox_2_currentTextChanged(const QString &arg1)
{
    this->algorithm=arg1;
}

void MainWindow::on_start_clicked()
{
    cur_step=1;//点击开始转换之后步骤就从1开始计数
    ui->next_step->setEnabled(true);
    //上方信息提示框内容删除
    ui->textBrowser->clear();
    //删除三个地址内容
    ui->va_h->clear();
    ui->va_l->clear();
    ui->pa_h_->clear();
    ui->pa_l_->clear();
    ui->ca_tag->clear();
    ui->ca_bias->clear();
    ui->ca_index->clear();
    //删除每一步的信息输出信息
    ui->cur_info->clear();
    QString addr=ui->lineEdit->text();//从输入框中获取逻辑地址
    int adr=addr.toInt();
    int va_h,va_l,ll,hh;
    if(adr>=mem_size+out_mem_size)
    {
        ui->cur_info->setText("输入不合法!\n逻辑地址大于内存容量+外存容量");
        return;
    }
    if(addr.length()!=0)
    {
        va_h=adr/page_size;//虚页号
        va_l=adr%page_size;//页内偏移地址
    }
    else
    {
        va_h=0;
        va_l=0;
    }
    ll=log2(page_size);//页内偏移地址的长度=log2(页大小)
    hh=log2(mem_size+out_mem_size)-ll;//逻辑地址长度=log2(内存大小+外存大小)
    ui->va_h->setText(QString("%1").arg(va_h, hh, 2, QLatin1Char('0')));
    ui->va_l->setText(QString("%1").arg(va_l, ll, 2, QLatin1Char('0')));
    ui->textBrowser->insertPlainText(QString("1.逻辑地址：%1\n").arg(adr));
}

void MainWindow::on_determine_clicked()
{
    ui->SecondStep->show();
    ui->setting_continer->setEnabled(false);//第一步中的设置设为不可用
    SecondStepInit();
}

void MainWindow::reset_all()//当第二步中点击“”退出的时候，必须要删除这些控件
{
    //删除四个容器
    page->container.clear();
    mem->container.clear();
    cache->container.clear();
    out_mem->container.clear();
    delete mem;
    delete page;
    delete cache;
    delete out_mem;
    mem=NULL;
    page=NULL;
    cache=NULL;
    out_mem=NULL;
    //上方信息提示框内容删除
    ui->textBrowser->clear();
    //删除地址输入框内容
    ui->lineEdit->clear();
    //删除三个地址内容
    ui->va_h->clear();
    ui->va_l->clear();
    ui->pa_h_->clear();
    ui->pa_l_->clear();
    ui->ca_tag->clear();
    ui->ca_bias->clear();
    ui->ca_index->clear();
    //删除每一步的信息输出信息
    ui->cur_info->clear();

}
void MainWindow::on_quit_clicked()
{
    reset_all();
    ui->SecondStep->hide();
    ui->setting_continer->setEnabled(true);//第一步中的设置设为可用
    QLayout *l=ui->my_view->layout();//一定要删除布局
    delete l;
}

void MainWindow::on_reset_clicked()
{
    ui->path_num_comboBox->setCurrentIndex(0);
    ui->mem_size_comboBox->setCurrentIndex(0);
    ui->page_size_comboBox->setCurrentIndex(0);
    ui->cache_sizze_comboBox->setCurrentIndex(0);
    ui->cache_block__size_comboBox->setCurrentIndex(0);
    ui->algorithmcomboBox_2->setCurrentIndex(0);
}

QPropertyAnimation* MainWindow::moveAtoB(QLabel *a, QWidget *pa, QLabel *b, QWidget *pb,QWidget *reference,int mode)//控件a,控件a的父控件,控件b，控件b的夫控件
{
    MyLabel *tmp_a=new MyLabel();
    QPoint pos_a=a->pos();
    QSize size_a=a->size();
    tmp_a->setParent(reference);
    pos_a=pa->mapToGlobal(pos_a);//转绝对位置
    pos_a=reference->mapFromGlobal(pos_a);//绝对转相对
    tmp_a->setGeometry(pos_a.x(),pos_a.y(),size_a.width(),size_a.height());
    tmp_a->setText(a->text());
    tmp_a->setStyleSheet(a->styleSheet());
    tmp_a->show();

    //创建b的拷贝主要是geomtry好像不是一个对象，只能作为对象的属性
    MyLabel *tmp_b=new MyLabel();
    QPoint pos_b=b->pos();
    QSize size_b=b->size();
    pos_b=pb->mapToGlobal(pos_b);//转绝对位置
    pos_b=reference->mapFromGlobal(pos_b);//绝对转相对
    tmp_b->setParent(reference);
    tmp_b->setGeometry(pos_b.x(),pos_b.y(),size_b.width(),size_b.height());

//    qDebug()<<tmp_a->geometry()<<' '<<tmp_b->geometry();//现在tmpa和tmpb都是相对于widget的位置了


    QPropertyAnimation *animation=new QPropertyAnimation
    (tmp_a,"geometry");
    animation->setDuration(move_time);
    animation->setStartValue(tmp_a->geometry());
    animation->setEndValue(tmp_b->geometry());
    animation->start(QAbstractAnimation::DeleteWhenStopped);//动画结束后删除动画对象（不是删除被控制的对象）

    connect(animation, &QPropertyAnimation::finished, [=] {//这里要实现在动画播放完毕后删除tmp对象的效果，必须用槽函数
               delete tmp_a;
               delete tmp_b;
               if(mode==1)//页表到物理地址
                ui->pa_h_->setText(a->text());//更新物理地址的高位
               else if(mode==2)//逻辑地址到物理地址
                ui->pa_l_->setText(a->text());//更新物理地址得低位
               else if(mode==3)//内存移动到cache
               {
                   b->setStyleSheet(a->styleSheet());
                   b->setText(a->text());
               }
               else if(mode==4)//cache_tag移动
               {
                   b->setText(a->text());
               }
               else if(mode==5)//外存移动到内存
               {
                   //交换下样式
                   QString bstyle=b->styleSheet();
                    b->setStyleSheet(a->styleSheet());
                    a->setStyleSheet(bstyle);
               }
               else if(mode==6)//逻辑地址到页表
               {
                   b->setText(a->text());
                   b->setStyleSheet(a->styleSheet());
               }
               isclicked=false;
            });
    return animation;
}

int MainWindow::read_cache(int cache_index,int tag)//给出cache的index和物理地址的tag
{
    //cache_index是cache的组索引
    for(int i=0;i<path_num;i++)
    if((cache->container)[cache_index+i]->tag==tag&&(cache->container)[cache_index+i]->status==1)
    {
        qDebug()<<"命中cache";
        return 1;
    }

    //一组内的所有tag都没有命中，就让这一组的第i个cache块的tag=物理地址的tag，并把数据存进去
    int full=0;
    for(int i=0;i<path_num;i++)
    {
        if((cache->container)[cache_index+i]->tag==-1)
        {
            (cache->container)[cache_index+i]->tag=tag;
            (cache->container)[cache_index+i]->status=1;
            break;
        }
        else
        {
            full++;
        }
    }
    if(full==path_num)
    {
        (cache->container)[cache_index]->tag=tag;
        (cache->container)[cache_index]->status=1;
    }
    return 0;
}
int MainWindow::LRU(int virtual_page)//逻辑地址
{
    int index;
    int max_count=-2;
    for(int i=0;i<page_num;i++)//找到count最大的那个表项 ，count值越大表示其最近最不常用
    {
        if((page->container)[i]->count>max_count)
        {
            max_count=(page->container)[i]->count;
            index=i;
        }
    }
    (page->container)[index]->pageNum=virtual_page;//填入虚页号
    (page->container)[index]->count=0;//同时计数清零
    QLayoutItem *t=page_layout->itemAtPosition(index+1,2);
    QLabel * page_count=qobject_cast<QLabel *>(t->widget());
    page_count->setText(QString::number( (page->container)[index]->count));
    return index;
}

int MainWindow::MyRandom(int virtual_page)
{
    int index=rand()%page_num;
    (page->container)[index]->pageNum=virtual_page;//填入虚页号
    (page->container)[index]->count=0;//同时计数清零
    return index;
}

void MainWindow::on_next_step_clicked()
{
    QString page_num_b=ui->va_h->text();//虚页号
    QString page_bias_b=ui->va_l->text();//页内偏移
    bool ok;
    int page_num_d=page_num_b.toInt(&ok,2);//读虚页号
    int page_bias_d=page_bias_b.toInt(&ok,2);//读虚页号
    if(!isclicked)
    {
        isclicked=true;
        switch(cur_step)
        {
            case 1:
            {
//                qDebug()<<"第一步";
                mem_num=locate(page_num_d);

                if(mem_num==-1)//页表中没找到
                {
                    ui->cur_info->setText("step1:查页表，调用替换算法");
                    ui->textBrowser->insertPlainText("2.缺页，调用替换算法\n");
                    int virtual_address=page_num_d*page_size+page_bias_d;
                    int out_mem_block_num=(virtual_address-mem_size)/page_size;//外存页号
                    int p_index;
                    if(algorithm=="LRU")
                    {
                        p_index=LRU(page_num_d);
                    }

                    else
                    {
                        qDebug()<<algorithm;
                        p_index=MyRandom(page_num_d);
                        qDebug()<<p_index;
                    }

                    int m_index=page->container[p_index]->memNum;
                    page->container[p_index]->pageNum=page_num_d;
                    for(int i=0;i<page_size;i++)
                    {
                        moveAtoB(out_mem->container[out_mem_block_num*page_size+i],out_mem,mem->container[m_index*page_size+i],mem,ui->my_view,5);
                    }
                    QLayoutItem *t=page_layout->itemAtPosition(p_index+1,0);
                    MyLabel * page_index=qobject_cast<MyLabel *>(t->widget());
                    moveAtoB(ui->va_h,ui->SecondStep,page_index,page,ui->SecondStep,6);
                    break;
                }
                else
                {
                    ui->cur_info->setText("step1：查页表");
                    ui->textBrowser->insertPlainText("2.页表命中\n");
                    //1 根据逻辑地址查页表，页表虚页号高亮闪烁；
                    int p_index;
                    for(int i=0;i<page_num;i++)
                    {
                        if(page_num_d==page->container[i]->pageNum) p_index=i;
                    }
                    QLayoutItem *t=page_layout->itemAtPosition(p_index+1,0);
                    MyLabel * page_index=qobject_cast<MyLabel *>(t->widget());
                    QPropertyAnimation *animation = new QPropertyAnimation(page_index,"color");
                    animation->setDuration(splash_time);
                    animation->setStartValue(QColor(255, 85, 0));
                    animation->setEndValue(QColor(240,240,240));
                    animation->start(QAbstractAnimation::DeleteWhenStopped);
                    animation->setLoopCount(3);
                    connect(animation, &QPropertyAnimation::finished, [=]{
                        cur_step=2;
                        page_index->setStyleSheet("background-color:rgb(255,85,0)");
                        isclicked=false;
                    });
                    break;
                }
            }

            case 2:
            {
                ui->cur_info->setText("step2:拼接物理地址");
                int p_index;
                for(int i=0;i<page_num;i++)
                {
                    if(page_num_d==page->container[i]->pageNum) p_index=i;
                }
                //2 从页表中把物理块号移动到逻辑地址的高位，逻辑地址的低位移动到物理地址的低位
                QPropertyAnimation *anime1=moveAtoB((page->container)[p_index],page,ui->pa_h_,ui->SecondStep,ui->SecondStep,1);
                QPropertyAnimation *anime2=moveAtoB(ui->va_l,ui->SecondStep,ui->pa_l_,ui->SecondStep,ui->SecondStep,2);
                connect(anime2, &QPropertyAnimation::finished, [=]{
                    cur_step=3;
                    isclicked=false;
                });
                break;
            }
            case 3:
            {
            ui->cur_info->setText("step3:切分cache地址");
                //3 更新cache地址
                physical_address=mem_num*page_size+page_bias_d;
                ui->textBrowser->insertPlainText(QString("3.物理地址：%1\n").arg(physical_address));
                int cache_bias=physical_address%cache_block_size;
                //cache块/组索引是物理地址/cache块大小%组数
                cache_index=physical_address/cache_block_size%(cache_size/cache_block_size/path_num);
                //cache的tag是物理地址/(cache大小/path_num)
                cache_tag=physical_address/(cache_size/path_num);
                ui->ca_tag->setText(QString("%1").arg(cache_tag,(int)log2((page_num*page_size)/(cache_size/path_num)), 2, QLatin1Char('0')));
                ui->ca_index->setText(QString("%1").arg(cache_index,(int)log2(cache_size/cache_block_size/path_num), 2, QLatin1Char('0')));
                if(cache_block_size!=1)
                ui->ca_bias->setText(QString("%1").arg(cache_bias,(int)log2(cache_block_size), 2, QLatin1Char('0')));
                isclicked=false;
                cur_step=4;
                break;
            }
            case 4:
            {

                cache_index=cache_index*path_num;
                int mem_block_num=physical_address/cache_block_size;//获得内存的块号
                if(!read_cache(cache_index,cache_tag))//cache不命中，函数已经将对应得tag改过来了
                {
                    ui->cur_info->setText("step4:访问cache未命中，调入内存块，\n运行结束，请输入新地址或者退出");
                    ui->textBrowser->insertPlainText("4.cache未命中\n");
                    int full=0;
                    for(int i=0;i<path_num;i++)
                    {
                        if((cache->container)[cache_index+i]->tag==cache_tag)
                        {

                            for(int j=0;j<cache_block_size;j++)
                            moveAtoB((mem->container)[mem_block_num*cache_block_size+j],mem,((cache->container)[cache_index+i]->data)[j],cache,ui->my_view,3);
                            QLayoutItem *t1=cache_layout->itemAtPosition(cache_index+i+1,0);
                            MyLabel * c_index=qobject_cast<MyLabel *>(t1->widget());
                            moveAtoB(ui->ca_tag,ui->SecondStep,c_index,cache,ui->SecondStep,4);
                            break;
                        }
                        else
                        {
                            full++;
                        }
                    }
                    if(full==path_num)
                    {
                        for(int i=0;i<cache_block_size;i++)
                        moveAtoB((mem->container)[mem_block_num*cache_block_size+i],mem,((cache->container)[cache_index]->data)[i],cache,ui->my_view,3);
                        QLayoutItem *t1=cache_layout->itemAtPosition(cache_index+1,0);
                        MyLabel * c_index=qobject_cast<MyLabel *>(t1->widget());
                        moveAtoB(ui->ca_tag,ui->SecondStep,c_index,cache,ui->SecondStep,4);
                    }
                }
                else
                {
                    ui->cur_info->setText("step4:访问cache命中,\n运行结束，请输入新地址或者退出");
                    ui->textBrowser->insertPlainText("4.cache命中");
                    isclicked=false;
                }
                cur_step=1;
                ui->next_step->setEnabled(false);
                break;
            }
            default:
                qDebug()<<"步骤出现错误！";
                break;
        }
    }

}

void MainWindow::open_setting()
{
    setting *myset=new setting;
    connect(myset,SIGNAL(sendinfo(int,int,int,int)),this,SLOT(getinfo(int,int,int,int)));
    myset->show();
    myset->setWindowTitle("参数设置");
    myset->setWindowIcon(QIcon(":/setting.svg"));
    myset->setAttribute(Qt::WA_DeleteOnClose);//关闭后释放资源
}

void MainWindow::open_use()
{
    use_displayer *myuse=new use_displayer;
    myuse->show();
    myuse->setWindowIcon(QIcon(":/说明.svg"));
    myuse->setWindowTitle("使用说明");
    myuse->setAttribute(Qt::WA_DeleteOnClose);//关闭后释放资源
}

void MainWindow::getinfo(int a, int b, int c, int d)
{
    width=a;
    height=b;
    splash_time=c;
    move_time=d;
}


